/***************************************************************************************************
*Copyright(C),2010-2017,Sumscope
*FileName	:  TableCodec.h
*Author	:  scofined.qi
*Version	:  1.0
*Date		:  2019/09/11
*Desc		:  //用于主要说明此程序文件完成的主要功能
*Relation :
*Others	:  //其他内容说明
*Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
*History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#ifndef TABLECODEC_CPP_9B8F1A8F_4C30_4583_A79D_1023BABD2F2E
#define TABLECODEC_CPP_9B8F1A8F_4C30_4583_A79D_1023BABD2F2E
#include <memory>
#include <vector>
#include "TableCodecCommon.h"
#include "StopCodec.h"
#include "FieldCollector.h"
namespace qb{
	namespace proto{
		class FieldCollector;
		typedef FieldCollector* FieldCollectorPtr;

		/*
		表格编解码
		用法:
		1.编码
			TableCodec codec;
			codec.Init(row,col,types);//设置共有多少行,多少列,每列类型

			// 收集全部数据
			for( record : records)
			{
				for( field : record.GetFields())
					codec.AddField(col,field);
			}

			// 将收集到的数据编码到一块内存中
			codec.Encode(buf,capcity);
		
		2.解码
			// 编解码要用不同的TableCodec实例,因为里面的VarValue中的str在编码/解码后会被清空
			// 返回的VarValue中的字符串指针在下次会被清空或者复用,不要保存,要拷贝出来
			TableCodec codec;
			codec.Decode(buf,size);

			const VarValue& codec.GetField(int row,int col);
		*/
		typedef std::map<FieldKey, FieldStat> FieldStatMap;
		typedef std::vector<FieldCollectorPtr> CollectorArray;
		typedef std::map<std::string, std::string> NameMap;
		typedef std::vector<std::string>		NameVec;
		class SSPROTOAPI TableCodec : public VarAllocator{
			CollectorArray		m_collectors;		//
			CollectorArray		m_dicts;			//	
			int					m_row;				//
			int					m_lastcol;			// 收集时上一次访问的列
			VarValue			m_blank;			// 空值
			OnceAllocator		m_page;
			char*				m_zbuf;				// 内部压缩的缓冲区
			int					m_zbuf_size;
			bool				m_use_key;
			bool				m_use_zip;
			SeqConvertMap		m_key_convert_map;
		public:
			TableCodec();
			~TableCodec();

			bool IsUseKey()const{ return m_use_key; }
			void SetUseKey(bool useKey){ m_use_key = useKey; }
		public://编码
			void AddRow(void);
			TableCodec* Copy();

			void AddField(const FieldKey& key,int row, const char* str, int len);
			void AddField(const FieldKey& key,int row, double d);
			void AddField(const FieldKey& key,int row, int i);
			void AddField(const FieldKey& key,int row, unsigned int i);
			void AddField(const FieldKey& key,int row, i64 i);
			void AddField(const FieldKey& key,int row, ui64 i);

			// 为所有列补足默认值/缺省值
			void AddDefaults(int row);

			int  Encode(unsigned char* buf, int capcity,bool& zipped);
			FieldCollectorPtr GetCollector(const std::string& key, bool bConvertKey = false);
			FieldCollectorPtr FindCollector(const std::string& key, bool bConvertKey = false);
			FieldCollectorPtr FindCollector(int index)const ;
			int GetCollectorIndex(const std::string& key);
			void InitConvertMap(std::vector<FieldKey>& vecKey); //初始化映射key表
		public://测试
			void RemoveCollector(const std::string& key);
			NameMap ChangeNumberAsKeys();
			NameMap GetNameMap();
		public://编解码
			int GetRow()const;
			int GetCol()const;
			int  Decode(unsigned char* buf, int size);
		protected:
			void DecodeDicts(StopCodec& decoder, int size, CollectorArray& dicts);
			FieldCollectorPtr DecodeField(StopCodec& decoder, int row, unsigned char flag, kEncodeType type);
		public://比较值
			bool EqualValues(const TableCodec& table)const;
		public://统计接口
			int GetStat(FieldStatMap& stat);
		public:
			// 自身管理内容,拷贝,交给VarValue中存储
			virtual char* AllocString(const char* str, int len);
			virtual void Reset();
			kEncodeType DeduceNameType(kNameType& nametype,std::vector<IncArray>& arrays);
			void PrepareBuffer(int size);

			void FixConvertValue(VarValue& fieldValue, kEncodeType type);
			FieldCollectorPtr DecodeColumn(StopCodec& decoder, int ncount, int colIndex);
		};

		class SSPROTOAPI ZSTD{
		public:
			static const char* versionString(void);
			static size_t compress(void* dst, size_t dstCapacity,
				const void* src, size_t srcSize,
				int compressionLevel);
			static size_t decompress(void* dst, size_t dstCapacity,
				const void* src, size_t compressedSize);
			static unsigned long long getFrameContentSize(const void *src, size_t srcSize);
			static size_t      compressBound(size_t srcSize);
			static unsigned    isError(size_t code);
			static const char* getErrorName(size_t code);
			static int         minCLevel(void);
			static int         maxCLevel(void);
		};
	}//namespace base;
}//namespace ss;
#endif
